﻿using System;
using System.Collections.Generic;

namespace Fadd.Logging
{
	/// <summary>
	/// A logger.
	/// </summary>
	public interface ILogger
	{
		/// <summary>
		/// Gets minimum log level that can be logged.
		/// </summary>
		LogLevel MinLevel { get; }

		/// <summary>
		/// Gets or sets logger name.
		/// </summary>
		string Name { get; set; }

		/// <summary>
		/// Gets or sets name space to log.
		/// </summary>
		string NameSpace { get; set; }

		/// <summary>
		/// Targets that this logger writes to.
		/// </summary>
		IEnumerable<ITarget> Targets { get; }

		/// <summary>
		/// Used to be able to trace program execution.
		/// </summary>
		/// <remarks>
		/// Very detailed log messages, potentially of a high frequency and volume
		/// </remarks>
		/// <param name="message">Log message.</param>
		void Trace(string message);

		/// <summary>
		/// Used to be able to trace program execution.
		/// </summary>
		/// <remarks>
		/// Very detailed log messages, potentially of a high frequency and volume
		/// </remarks>
		/// <param name="message">Log message.</param>
		/// <param name="exception">Exception thrown in application.</param>
		void Trace(string message, Exception exception);

		/// <summary>
		/// Entries that are helpful when debugging.
		/// </summary>
		/// <param name="message">Log message.</param>
		void Debug(string message);

		/// <summary>
		/// Entries that are helpful when debugging.
		/// </summary>
		/// <param name="message">Log message.</param>
		/// <param name="exception">Exception thrown in application.</param>
		void Debug(string message, Exception exception);

		/// <summary>
		/// Information that can be helpful during normal program execution.
		/// </summary>
		/// <param name="message">Log message.</param>
		void Info(string message);

		/// <summary>
		/// Information that can be helpful during normal program execution.
		/// </summary>
		/// <param name="message">Log message.</param>
		/// <param name="exception">Exception thrown in application.</param>
		void Info(string message, Exception exception);

		/// <summary>
		/// Something unexpected happened, but program execution can continue as expected.
		/// </summary>
		/// <param name="message">Log message.</param>
		void Warning(string message);

		/// <summary>
		/// Something unexpected happened, but program execution can continue as expected.
		/// </summary>
		/// <param name="message">Log message.</param>
		/// <param name="exception">Exception thrown in application.</param>
		void Warning(string message, Exception exception);

		/// <summary>
		/// Something went really wrong. Program execution cannot continue as expected,
		/// but there is no need to shutdown the program.
		/// </summary>
		/// <param name="message">Log message.</param>
		void Error(string message);

		/// <summary>
		/// Something went really wrong. Program execution cannot continue as expected,
		/// but there is no need to shutdown the program.
		/// </summary>
		/// <param name="message">Log message.</param>
		/// <param name="exception">Exception thrown in application.</param>
		void Error(string message, Exception exception);

		/// <summary>
		/// Major disaster, program ought to be shut down and restarted.
		/// </summary>
		/// <param name="message">Log message.</param>
		void Fatal(string message);

		/// <summary>
		/// Major disaster, program ought to be shut down and restarted.
		/// </summary>
		/// <param name="message">Log message.</param>
		/// <param name="exception">Exception thrown in application.</param>
		void Fatal(string message, Exception exception);


		/// <summary>
		/// Load configuration
		/// </summary>
		/// <param name="configuration">Configuration to load</param>
		/// <remarks>
		/// Can only be invoked during startup.
		/// </remarks>
		/// <exception cref="InvalidOperationException">Configuration have already been specified.</exception>
		void LoadConfiguration(LoggerConfiguration configuration);

		/// <summary>
		/// Determines if this logger can log the specified name space.
		/// </summary>
		/// <param name="value">Name space to check</param>
		/// <returns>true if name space can be logged; otherwise false.</returns>
		bool CanLog(string value);
	}
}